package com.netflexitysolutions.amazonws.ec2.internal.operations;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesExecutableBySetType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesExecutableByType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesInfoType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesItemType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesOwnerType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesOwnersType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesResponseItemType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesResponseType;
import com.amazonaws.ec2.doc._2009_04_04.DescribeImagesType;
import com.amazonaws.ec2.doc._2009_04_04.ProductCodesSetItemType;
import com.netflexitysolutions.amazonws.ec2.Architecture;
import com.netflexitysolutions.amazonws.ec2.EC2;
import com.netflexitysolutions.amazonws.ec2.ImageDescription;
import com.netflexitysolutions.amazonws.ec2.ImageState;
import com.netflexitysolutions.amazonws.ec2.ImageType;

public class DescribeImagesOperation extends OperationExecutor<DescribeImagesType, List<ImageDescription>> {
	
	private Set<String> imageIds;
	
	private Set<String> ownedBy;
	
	private Set<String> executableBy;
	
	public DescribeImagesOperation(EC2 ec2, Set<String> imageIds, 
			Set<String> ownedBy, Set<String> executableBy) {
		super(ec2);
		this.imageIds = imageIds != null ? imageIds : new HashSet<String>();
		this.ownedBy = ownedBy != null ? ownedBy : new HashSet<String>();
		this.executableBy = executableBy != null ? executableBy : new HashSet<String>();
	}

	@Override
	protected List<ImageDescription> call(DescribeImagesType request) {
		request.setExecutableBySet(createExecutableByElement());
		request.setOwnersSet(createOwnedByElement());
		request.setImagesSet(createImageIdsElement());
		
		DescribeImagesResponseType response = getEC2().getService().describeImages(request);
		
		List<ImageDescription> result =  new ArrayList<ImageDescription>();
		if (response.getImagesSet() != null) {
			List<DescribeImagesResponseItemType> list = response.getImagesSet().getItem();
			for (DescribeImagesResponseItemType item : list) {
				result.add(toDomainType(item));
			}
		}
		return result;
	}
	
	private DescribeImagesExecutableBySetType createExecutableByElement() {
		DescribeImagesExecutableBySetType element = new DescribeImagesExecutableBySetType();
		List<DescribeImagesExecutableByType> list = element.getItem();
		for (String exec : executableBy) {
			DescribeImagesExecutableByType item = new DescribeImagesExecutableByType();
			item.setUser(exec);
			list.add(item);
		}
		return element;
	}
	
	private DescribeImagesOwnersType createOwnedByElement() {
		DescribeImagesOwnersType element = new DescribeImagesOwnersType();
		List<DescribeImagesOwnerType> list = element.getItem();
		for (String owner : ownedBy) {
			DescribeImagesOwnerType item = new DescribeImagesOwnerType();
			item.setOwner(owner);
			list.add(item);
		}
		return element;
	}
	
	private DescribeImagesInfoType createImageIdsElement() {
		DescribeImagesInfoType element = new DescribeImagesInfoType();
		List<DescribeImagesItemType> list = element.getItem();
		for (String imageId : imageIds) {
			DescribeImagesItemType item = new DescribeImagesItemType();
			item.setImageId(imageId);
			list.add(item);
		}
		return element;
	}
	
	private ImageDescription toDomainType(DescribeImagesResponseItemType item) {
		ImageDescription image = new ImageDescription();
		image.setId(item.getImageId());
		image.setKernelId(item.getKernelId());
		image.setLocation(item.getImageLocation());
		image.setPlatform(item.getPlatform());
		image.setOwnerId(item.getImageOwnerId());
		image.setPublic(item.isIsPublic());
		image.setRamdiskId(item.getRamdiskId());
		image.setArchitecture(Architecture.architectureForName(item.getArchitecture()));
		image.setState(ImageState.imageStateForName(item.getImageState()));
		image.setType(ImageType.imageTypeForName(item.getImageType()));
		Set<String> codes =  new HashSet<String>();
		image.setProductCodes(codes);
		if (item.getProductCodes() != null) {
			List<ProductCodesSetItemType> xmlCodes = item.getProductCodes().getItem();
			for (ProductCodesSetItemType xmlCode : xmlCodes) {
				codes.add(xmlCode.getProductCode());
			}
		}
		return image;
	}
}
